import * as vscode from "vscode";

interface VariableValueMap {
  [key: string]: string[];
}

export class CSSVariableParser {
  variableMap: Map<string, { value: string; comment?: string }> = new Map();
  valueToVars: VariableValueMap = {};

  async collectVariables() {
    const config = vscode.workspace.getConfiguration("cssVariableAutocomplete");
    const scanDirs = config.get<string[]>("scanDirs", ["**"]);
    const patterns = scanDirs.map((dir) => `${dir}/**/*.{css,scss}`);
    this.variableMap.clear();
    this.valueToVars = {};

    // 查找匹配的文件
    const files = await Promise.all(
      patterns.map((pattern) => vscode.workspace.findFiles(pattern))
    ).then((results) => results.flat());

    for (const file of files) {
      const content = (await vscode.workspace.openTextDocument(file)).getText();
      // if (file.path.includes("index")) console.log(content);
      this.parseCSSVariables(content);
    }
    this.buildValueMapping();
  }

  private parseCSSVariables(text: string) {
    const regex =
      /(--|\$)([\w-]+)\s*:\s*([^;]+?)\s*;(?:\/\*\s*(.*?)\s*\*\/|\/\/\s*(.*?)|(\s*)){0,}\r*\n/g;
    let match;
    while ((match = regex.exec(text)) !== null) {
      const varName = `${match[1]}${match[2]}`;
      const value = match[3].trim();
      const comment = (match[4] || match[5] || "").trim();
      this.variableMap.set(varName, { value, comment });
    }
  }

  private getCSSVariables(text: string) {
    const regex = /(--|\$)([\w-]+)\s*:\s*([^;]+?)\s*;\s*\r\n/g;
    let match;
    const cssVariablesArray: string[] = [];
    while ((match = regex.exec(text)) !== null) {
      const value = match[3].trim();
      cssVariablesArray.push(value);
    }
    return cssVariablesArray;
  }

  private resolveValue(
    varName: string,
    visited = new Set<string>()
  ): string | undefined {
    if (visited.has(varName)) return undefined;
    visited.add(varName);
    const valueItem = this.variableMap.get(varName);
    if (!valueItem) return undefined;
    const varMatch = valueItem.value.match(/var\((--|\$)([\w-]+)\)/);
    if (varMatch) {
      return (
        this.resolveValue(`${varMatch[1]}${varMatch[2]}`, visited) ||
        valueItem.value
      );
    }
    return valueItem.value;
  }

  private buildValueMapping() {
    this.variableMap.forEach((value, varName) => {
      const resolvedValue = this.resolveValue(varName);
      if (resolvedValue) {
        this.valueToVars[resolvedValue] = this.valueToVars[resolvedValue] || [];
        this.valueToVars[resolvedValue].push(varName);
      }
    });
  }

  getGestions(currentText: string): {
    key: string;
    value: { key: string; value: string; comment: string | undefined }[];
  }[] {
    const arr: {
      key: string;
      value: { key: string; value: string; comment: string | undefined }[];
    }[] = [];
    const cssVarValueArray = this.getCSSVariables(currentText).map((item) =>
      item.toLocaleLowerCase()
    );
    Object.entries(this.valueToVars).forEach(([value, vars]) => {
      if (cssVarValueArray.find((str) => value.toLowerCase().startsWith(str))) {
        vars.forEach((varName) => {
          const { comment } = this.variableMap.get(varName) || {};
          arr.push({
            key: value,
            value: [{ key: varName, value: value, comment: comment }],
          });
        });
      }
    });
    return arr;
  }

  getSuggestions(currentValue: string): vscode.CompletionItem[] {
    const suggestions: vscode.CompletionItem[] = [];
    const currentLower = currentValue.toLowerCase();
    Object.entries(this.valueToVars).forEach(([value, vars]) => {
      if (value.toLowerCase().startsWith(currentLower)) {
        vars.forEach((varName) => {
          const item = new vscode.CompletionItem(
            varName,
            vscode.CompletionItemKind.Text
          );
          item.insertText = `var(${varName})`;
          item.filterText = value;
          const { comment } = this.variableMap.get(varName) || {};
          item.detail = `${value} ` + (comment ? comment : "");
          suggestions.push(item);
        });
      }
    });
    return suggestions;
  }
}
